package com.battle.service.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.battle.pojo.entity.Exam;
import com.battle.pojo.entity.Organization;
import com.battle.pojo.entity.QuestionBankDetails;
import com.battle.pojo.entity.User;
import com.battle.pojo.param.exam.*;
import com.battle.pojo.vo.exam.*;
import com.battle.pojo.dto.exam.*;
import com.battle.service.repository.in.ExamRepository;
import com.battle.service.repository.in.OrganizationRepository;
import com.battle.service.repository.in.QuestionBankDetailsRepository;
import com.battle.service.repository.in.UserRepository;
import com.battle.service.service.in.ExamService;
import com.google.gson.Gson;
import nirvana.core.domains.vo.PageResult;
import nirvana.core.exceptions.BizException;
import nirvana.core.utils.ids.IdGenerator;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;


import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 【描 述】：考试管理服务
 * 【环 境】：J2SE 17
 * 【详 细】：
 */
@Service
public class ExamServiceImpl implements ExamService {

    private final ExamRepository examRepository;
    private final UserRepository userRepository;
    private final OrganizationRepository organizationRepository;
    private final QuestionBankDetailsRepository detailsRepository;

    public ExamServiceImpl(ExamRepository examRepository, UserRepository userRepository, OrganizationRepository organizationRepository, QuestionBankDetailsRepository detailsRepository) {
        this.examRepository = examRepository;
        this.userRepository = userRepository;
        this.organizationRepository = organizationRepository;
        this.detailsRepository = detailsRepository;
    }


    /**
     * 创建考试管理
     *
     * @param param
     */
    @Override
    public void createExam(CreateExamParam param) {
        Exam exam = new Exam();
        BeanUtils.copyProperties(param, exam);
        Long id = IdGenerator.SNOW.generate();
        exam.setId(id);

        Gson gson = new Gson();
        //考核范围ids
        List<Long> scopeIds = param.getExamScopeIds();
        if (CollectionUtil.isNotEmpty(scopeIds)) {
            String idsString = gson.toJson(scopeIds);
            exam.setExamScopeIds(idsString);
        }

        //考核题库ids
        List<Long> questionIds = param.getQuestionBankIds();
        if (CollectionUtil.isNotEmpty(questionIds)) {
            String idsString = gson.toJson(questionIds);
            exam.setQuestionBankIds(idsString);
        }

        //随机题目
        List<CreateRandomQuestionParam> randomQuestionList = param.getRandomQuestionJson();
        if (CollectionUtil.isNotEmpty(randomQuestionList)) {
            String idsString = gson.toJson(randomQuestionList);
            exam.setRandomQuestionJson(idsString);
        }

        //指定题目
        List<CreateAppointQuestionParam> appointQuestionList = param.getAppointQuestionJson();
        if (CollectionUtil.isNotEmpty(appointQuestionList)) {
            String idsString = gson.toJson(appointQuestionList);
            exam.setAppointQuestionJson(idsString);
        }

        exam.setStatus(0);
        examRepository.create(exam);
    }

    /**
     * 修改考试管理
     *
     * @param param
     */
    @Override
    public void editExam(EditExamParam param) {
        Long id = param.getId();
        Exam exam = examRepository.getByIdCheck(id);
        BeanUtils.copyProperties(param, exam);
        exam.setStatus(0);

        Gson gson = new Gson();
        //考核范围ids
        List<Long> scopeIds = param.getExamScopeIds();
        if (CollectionUtil.isNotEmpty(scopeIds)) {
            String idsString = gson.toJson(scopeIds);
            exam.setExamScopeIds(idsString);
        }

        //考核题库ids
        List<Long> questionIds = param.getQuestionBankIds();
        if (CollectionUtil.isNotEmpty(questionIds)) {
            String idsString = gson.toJson(questionIds);
            exam.setQuestionBankIds(idsString);
        }

        //随机题目
        List<CreateRandomQuestionParam> randomQuestionList = param.getRandomQuestionJson();
        if (CollectionUtil.isNotEmpty(randomQuestionList)) {
            String idsString = gson.toJson(randomQuestionList);
            exam.setRandomQuestionJson(idsString);
        }

        //指定题目
        List<CreateAppointQuestionParam> appointQuestionList = param.getAppointQuestionJson();
        if (CollectionUtil.isNotEmpty(appointQuestionList)) {
            String idsString = gson.toJson(appointQuestionList);
            exam.setAppointQuestionJson(idsString);
        }
        examRepository.edit(exam);
    }

    /**
     * 移除考试管理
     *
     * @param id
     */
    @Override
    public void removeExam(Long id) {
        Exam exam = examRepository.getByIdCheck(id);
        if (exam.getStatus() == 2 || exam.getStatus() == 3) {
            throw new BizException("考试已开始，无法删除");
        }
        examRepository.removeById(id);
    }

    /**
     * 启动/禁用考试管理
     *
     * @param id
     */
    @Override
    public void enabledExam(Long id) {
        Exam exam = examRepository.getByIdCheck(id);
        exam.setIsDisable(!exam.getIsDisable());
        examRepository.edit(exam);
    }

    /**
     * 获取考试管理详情
     *
     * @param id
     * @return
     */
    @Override
    public GetExamVo getExam(Long id) {
        Exam exam = examRepository.getByIdCheck(id);
        GetExamVo vo = new GetExamVo();
        BeanUtils.copyProperties(exam, vo);
        //考核范围ids
        List<Long> scopeIds = JSONUtil.toList(exam.getExamScopeIds(), Long.class);
        vo.setExamScopeIds(scopeIds);
        //考核题库ids
        List<Long> questionIds = JSONUtil.toList(exam.getQuestionBankIds(), Long.class);
        vo.setQuestionBankIds(questionIds);
        //随机题目
        if (JSONUtil.isJsonArray(exam.getRandomQuestionJson())) {
            List<CreateRandomQuestionParam> randomQuestionList = JSONUtil.toList(exam.getRandomQuestionJson(), CreateRandomQuestionParam.class);
            vo.setRandomQuestionJson(randomQuestionList);
        }
        //指定题目
        if (JSONUtil.isJsonArray(exam.getAppointQuestionJson())) {
            List<CreateAppointQuestionParam> appointQuestionList = JSONUtil.toList(exam.getAppointQuestionJson(), CreateAppointQuestionParam.class);
            if (CollectionUtil.isNotEmpty(appointQuestionList)) {
                //提取题目的id
                List<Long> questionIdList = appointQuestionList.stream().map(CreateAppointQuestionParam::getQuestionId).distinct().collect(Collectors.toList());

                //查询题目详情
                Map<Long, QuestionBankDetails> map = detailsRepository.getMap(questionIdList);
                List<AppointQuestionJsonVo> appointQuestionVoList = new ArrayList<>();

                if (CollectionUtil.isNotEmpty(map)) {
                    for (CreateAppointQuestionParam questionParam : appointQuestionList) {
                        QuestionBankDetails details = map.get(questionParam.getQuestionId());

                        AppointQuestionJsonVo appointQuestionVo = new AppointQuestionJsonVo();
                        BeanUtils.copyProperties(details, appointQuestionVo);
                        appointQuestionVo.setQuestionId(details.getId());
                        appointQuestionVo.setScore(questionParam.getScore());

                        appointQuestionVoList.add(appointQuestionVo);
                    }
                }
                vo.setAppointQuestionVoList(appointQuestionVoList);
            }
        }
        return vo;
    }

    /**
     * 撤回考试
     *
     * @param id
     */
    @Override
    public void recallExam(Long id) {
        Exam exam = examRepository.getByIdCheck(id);
        if (exam.getStatus() == 2 || exam.getStatus() == 3) {
            throw new BizException("考试已开始，无法撤回");
        }
        exam.setStatus(0);
        examRepository.edit(exam);
    }

    /**
     * 发布考试
     *
     * @param id
     */
    @Override
    public void publishExam(Long id) {
        Exam exam = examRepository.getByIdCheck(id);
        if (exam.getStatus() != 0) {
            throw new BizException("考试已发布，无法重复发布");
        }
        exam.setStatus(1);
        examRepository.edit(exam);
    }

    /**
     * 获取指定题目列表
     *
     * @param param
     * @return
     */
    @Override
    public PageResult<AppointQuestionJsonVo> getAppointQuestionList(GetExamListParam param) {
        if (param.getId() == null) throw new BizException("考试id不能为空");
        Exam exam = examRepository.getByIdCheck(param.getId());
        if (JSONUtil.isJsonArray(exam.getAppointQuestionJson())) {
            List<CreateAppointQuestionParam> appointQuestionList = JSONUtil.toList(exam.getAppointQuestionJson(), CreateAppointQuestionParam.class);
            if (CollectionUtil.isNotEmpty(appointQuestionList)) {
                //提取题目的id
                List<Long> questionIdList = appointQuestionList.stream().map(CreateAppointQuestionParam::getQuestionId).distinct().collect(Collectors.toList());
                SelectExamDto dto = new SelectExamDto();
                BeanUtils.copyProperties(param, dto);
                dto.setQuestionIds(questionIdList);
                Page<AppointQuestionJsonVo> page = examRepository.getAppointQuestionList(dto);

                //分数
                Map<Long, CreateAppointQuestionParam> map = appointQuestionList.stream().collect(Collectors.toMap(CreateAppointQuestionParam::getQuestionId, pojo -> pojo));
                for (AppointQuestionJsonVo record : page.getRecords()) {
                    CreateAppointQuestionParam questionParam = map.get(record.getQuestionId());
                    if (questionParam != null) {
                        record.setScore(questionParam.getScore());
                    }
                }

                return new PageResult<>(page.getRecords(), page);
            }
        }
        return new PageResult<>(new ArrayList<>(), new Page<>());
    }

    /**
     * 获取考试管理 列表
     *
     * @param param
     * @return
     */
    @Override
    public PageResult<GetExamListVo> getExamList(GetExamListParam param) {

        SelectExamDto dto = new SelectExamDto();
        BeanUtils.copyProperties(param, dto);
        Page<Exam> page = examRepository.selectExam(dto);
        List<Exam> examList = page.getRecords();
        List<GetExamListVo> list = new ArrayList<>();

        if (CollectionUtil.isNotEmpty(examList)) {
            //提取出创建人ids
            List<Long> userIds = examList.stream().map(Exam::getCreator).distinct().collect(Collectors.toList());
            Map<Long, User> userMap = userRepository.getMap(userIds);

            for (Exam exam : examList) {
                GetExamListVo vo = new GetExamListVo();
                BeanUtils.copyProperties(exam, vo);

                //创建人
                User create = userMap.get(exam.getCreator());
                if (create != null) {
                    vo.setCreateName(create.getName());
                }

                //考核范围
                if (JSONUtil.isJsonArray(exam.getExamScopeIds())) {
                    List<Long> scopeIds = JSONUtil.toList(exam.getExamScopeIds(), Long.class);
                    List<Organization> organizationList = organizationRepository.listByIds(scopeIds);
                    if (CollectionUtil.isNotEmpty(organizationList)) {
                        List<String> scopeNames = organizationList.stream().map(Organization::getName).collect(Collectors.toList());
                        vo.setExamScopeNames(scopeNames);
                    }
                }
                list.add(vo);
            }
        }

        return new PageResult<>(list, page);

    }

    /**
     * 获取考试管理下拉列表
     *
     * @param param
     * @return
     */
    @Override
    public List<GetExamDownListVo> getExamDownList(GetExamDownListParam param) {
        Exam po = new Exam();
        if (param != null) {
            BeanUtils.copyProperties(param, po);
        }
        List<Exam> examList = examRepository.getListByEntity(po);

        List<GetExamDownListVo> list = new ArrayList<>();
        for (Exam exam : examList) {
            GetExamDownListVo vo = new GetExamDownListVo();
            BeanUtils.copyProperties(exam, vo);
            list.add(vo);
        }
        return list;
    }


}



